#include <math.h>
#include <iostream>
#include <functional>

using std::cout;
using std::endl;
using std::bind;
using std::function;

//要实现多态
//1、面向对象的思想：继承 + 虚函数(纯虚函数)(运行的时候)
//2、基于对象的思想: std::bind + std::function(编译的时候)
class Figure
{
public:
    //using就是为了取别名
    using DisplayCallback = function<void()>;
    using AreaCallback = function<double()>;
    
    //利用回调函数的基本使用方法：注册回调函数与执行回调函数
    //setXXX代表的是注册
    void setDisplayCallback(DisplayCallback &&cb)
    {
        _displayCallback = std::move(cb);
    }

    void setAreaCallback(AreaCallback &&cb)
    {
        _areaCallback = std::move(cb);
    }

    //handleXXX代表是执行
    void handleDisplayCallback() const
    {
        if(_displayCallback)
        {
            _displayCallback();
        }
    }

    double handleAreaCallback() const
    {
        if(_areaCallback)
        {
            return _areaCallback();
        }
        else
        {
            return 0.0;
        }
    }

private:
    DisplayCallback _displayCallback;//子对象
    AreaCallback _areaCallback;//子对象

};

class Rectangle
{
public:
    Rectangle(double length = 0.0, double width = 0.0)
    : _length(length)
    , _width(width)
    {
        cout << "Rectangle(double = 0.0, double = 0.0)" << endl;
    }

    void display(int x) const 
    {
        cout << "Rectangle: ";
    }

    double area() const 
    {
        return _width * _length;
    }

    ~Rectangle()
    {
        cout << "~Rectangle()" << endl;
    }
private:
    double _length;
    double _width;
};

//Circle cir = 10;
class Circle
{
public:
    explicit
    Circle(double radius = 0.0)
    : _radius(radius)
    {
        cout << "Circle(double = 0.0)" << endl;
    }

    void show() const 
    {
        cout << "Circle: ";
    }

    double showArea() const 
    {
        return 3.14 * _radius * _radius;
    }
    ~Circle()
    {
        cout << "~Circle()" << endl;
    }

private:
    double _radius;
};

class Triangle
{
public:
    Triangle(double a= 0.0, double b = 0.0, double c = 0.0)
    : _a(a)
    , _b(b)
    , _c(c)
    {
        cout << "Triangle(double = 0.0, double = 0.0, double = 0.0)" << endl;
    }

    void print() const 
    {
        cout << "Triangle: ";
    }

    double printArea() const 
    {
        double tmp = (_a + _b + _c)/2;
        
        return sqrt(tmp * (tmp - _a) * (tmp - _b) * (tmp - _c));
    }

    ~Triangle()
    {
        cout << "~Triangle()" << endl;
    }

private:
    double _a;
    double _b;
    double _c;
};

void func(const Figure &fig)
{
    fig.handleDisplayCallback();
    cout << " 的面积: " << fig.handleAreaCallback() << endl;
}

int main(int argc, char *argv[])
{
    Rectangle rectangle(10, 20);
    Circle circle(10);
    Triangle triangle(3, 4, 5);

    Figure fig;
    fig.setDisplayCallback(bind(&Rectangle::display, &rectangle, 300));
    fig.setAreaCallback(bind(&Rectangle::area, &rectangle));
    func(fig);

    fig.setDisplayCallback(bind(&Circle::show, &circle));
    fig.setAreaCallback(bind(&Circle::showArea, &circle));
    func(fig);

    fig.setDisplayCallback(bind(&Triangle::print, &triangle));
    fig.setAreaCallback(bind(&Triangle::printArea, &triangle));
    func(fig);
    return 0;
}

